package com.lx.lxsql.execute.impl;

import com.lx.util.LX;
import com.lx.util.LXLog;
import com.lx.lxsql.entity.StatementInformation;
import com.lx.lxsql.entity.Field;
import com.lx.lxsql.entity.Table;
import com.lx.lxsql.execute.Execute;
import com.lx.lxsql.execute.ExecuteUtil;

import java.util.*;

import static com.lx.lxsql.entity.SIType.*;


public class CreateTableExecute extends Execute {

    @Override
    public boolean matching(LinkedList<StatementInformation> ls) {
        return ls.size()>1 && CREATE.isType(ls.get(0))
                && TABLE.isType(ls.get(1));
    }

    @Override
    public <T> T exec(ExecuteUtil util) {
        // 验证开头 create table
        util.exTypeNextList(CREATE,TABLE);
        // 开始解析成Table
        Table table = new Table();
        table.setTableName(util.exNextInType(WORD).getTxt());
        // 判断是否为(
        util.exNextInType(LP);
        do{
            StatementInformation sif = util.next();
            if (WORD.isType(sif)){
                Field field = new Field();
                field.setFieldName(sif.getTxt());
                StatementInformation fieldType = util.exNextInType(INT, DECIMAL, CHAR, VARCHAR, DATE, DATETIME);
                field.setType(fieldType.getSiType());
                switch (fieldType.getSiType()){
                    case CHAR:
                    case VARCHAR:
                        List<StatementInformation> len = util.exTypeNextList(LP, ISLONG, RP);
                        field.setLen1(Long.parseLong(len.get(1).getTxt()));
                        break;
                    case DECIMAL:
                        List<StatementInformation> len2 = util.exTypeNextList(LP, ISLONG,COM,ISLONG, RP);
                        field.setLen1(Long.parseLong(len2.get(1).getTxt()));
                        field.setLen2(Long.parseLong(len2.get(3).getTxt()));
                        break;
                }
                //设置字段其他信息 not null ; default ; comment;
                boolean b = setField(field, util);
                table.getFields().add(field);
                if (b){
                    break;
                }
            }else if (PRIMARY.isType(sif)){
                //设置主键约束
                if (setPrimaryKey(table, util)){
                    break;
                }
            }else{
                LX.exMsg("解析错误");
            }
        }while (true);
        LX.exMsg(util.hasNext(),"脚本异常!");
        //判断主键是否都存在
        checkPrimaryKey(table);
        //存储表信息
        System.out.println(table);
        return null;
    }

    //说明: 检查主键信息
    /**{ ylx } 2021/9/20 22:16 */
    private void checkPrimaryKey(Table table) {
        if (LX.isNotEmpty(table.getPrimaryKeys())){
            for (String p : table.getPrimaryKeys()) {
                boolean flag = true;
                for (Field field : table.getFields()) {
                    if (field.getFieldName().equals(p)){
                        flag = false;
                        break;
                    }
                }
                LX.exMsg(flag, "主键字段不存在!"+p);
            }
        }
    }

    //说明:设置表主键
    /**{ ylx } 2021/9/20 22:02 */
    private boolean setPrimaryKey(Table table, ExecuteUtil util) {
        LXLog.debug("开始设置主键约束");
        LX.exMsg(LX.isNotEmpty(table.getPrimaryKeys()),"主键设置重复!");
        List<String> keys = new ArrayList<>();
        List<StatementInformation> primaryKey = util.exTypeNextList(KEY, LP, WORD);
        keys.add(primaryKey.get(2).getTxt());
        while (true){
            StatementInformation jd = util.exNextInType(COM, RP);
            if (jd.getSiType() == RP){
                table.setPrimaryKeys(keys);
                StatementInformation end = util.exNextInType(COM, RP);
                // 后面是 ) 表示结束  , 还可以继续
                return RP.isType(end);
            }
            // 下一个字段
            StatementInformation key = util.exNextInType(WORD);
            LX.exMsg(keys.contains(key.getTxt()),"主键字段重复!");
            keys.add(key.getTxt());
        }
    }


    // 循环设置字段信息
    private boolean setField(Field field, ExecuteUtil util) {
        StatementInformation sif = util.exNextInType(RP,COM,NOT,DEFAULT,COMMENT);
        switch (sif.getSiType()){
            case RP:
                return true;
            case COM:
                return false;
            case NOT:
                LXLog.debug("设置字段非空!");
                util.exNextInType(NULL);
                LX.exMsg(field.isNotNull(),"not null 不能重复!");
                field.setNotNull(true);
                return setField(field,util);
            case DEFAULT:
                LXLog.debug("设置字段默认值!");
                StatementInformation s = util.exNextInType(STRING);
                LX.exMsg(LX.isNotEmpty(field.getDefaultStr()),"default 信息不能重复!");
                field.setDefaultStr(s.getTxt());
                return setField(field, util);
            case COMMENT:
                LXLog.debug("设置字段备注!");
                StatementInformation comment = util.exNextInType(STRING);
                LX.exMsg(LX.isNotEmpty(field.getComment()),"comment 信息不能重复!");
                field.setComment(comment.getTxt());
                return setField(field, util);
        }
        return false;
    }


}
